#ifndef __TIMER_H
#define __TIMER_H
#include "stdtype.h"

/* period of timer (Hz), 
   depends on the hardware timer call period, default 200 */
#define MX_TIMER_PERIOD TIMER_PERIOD

/* calculate the count */
#define MX_TIMER_S(second) (MX_TIMER_PERIOD * second)
#define MX_TIMER_MS(millisecond) ((millisecond % (1000 / MX_TIMER_PERIOD)) == 0 ?   \
                                  (millisecond / (1000 / MX_TIMER_PERIOD)) : (millisecond / (1000 / MX_TIMER_PERIOD) + 1))

/**
 * register a timer to system without the descriptor
 * @prototype: mx_timer_register(mx_timer_mode_t mode, mx_usize_t reload, mx_timer_func_t func);
 * @return: the descriptor of timer, never be mx_null
 */
#define mx_timer_register(mode, reload, func) ({    \
    static mx_timer_t _i_timer; \
    mx_timer_mount(&_i_timer, mode, reload, func);  \
    &_i_timer;  \
})

/* timer status */
typedef enum
{
    MX_TIMER_STATUS_DISABLE = 0U,
    MX_TIMER_STATUS_ENABLE,
    MX_TIMER_STATUS_TIMEOUT,
    MX_TIMER_STATUS_PAUSE
} mx_timer_status_t;

/* timer mode */
typedef enum
{
    MX_TIMER_MODE_ONESHOT = 0U,
    MX_TIMER_MODE_INTERVAL
} mx_timer_mode_t;

typedef struct mx_timer mx_timer_t, *mx_timer_pt;

/* prototype of timer callback function */
typedef void (* mx_timer_func_t) (mx_timer_pt ptimer);

/* timer object definition */
struct mx_timer
{
    volatile mx_uint8_t status;     // the runtime status of timer
    mx_uint8_t mode;                // interval or one-shot
    mx_usize_t reload;              // the reload value
    volatile mx_usize_t current;    // the current value
    mx_timer_func_t func;           // the callback funcion when timeout
    struct mx_timer* next;
};

/* mount a timer to system */
void mx_timer_mount (mx_timer_pt ptimer, mx_timer_mode_t mode,
                     mx_usize_t reload, mx_timer_func_t func);
/* umount a timer from system */
void mx_timer_umount (mx_timer_pt ptimer);
/* init the spcified timer */
void mx_timer_init (mx_timer_pt ptimer, mx_usize_t reload);
/* reset the spcified timer and stop it */
void mx_timer_reset (mx_timer_pt ptimer);
/* reset the current tick of timer and start it */
void mx_timer_restart (mx_timer_pt ptimer);
/* start the timer when the 'begin tick' not qeual to 0 */
void mx_timer_start (mx_timer_pt ptimer);
/* pause the timer while it is runing */
void mx_timer_pause (mx_timer_pt ptimer);
/* stop the timer while it is runing */
void mx_timer_stop (mx_timer_pt ptimer);
/* start the timer with new configuration */
void mx_timer_launch (mx_timer_pt ptimer, mx_usize_t reload);
/* bind a call back function to the timer */
void mx_timer_attach (mx_timer_pt ptimer, mx_timer_func_t func);
/* get the status of timer */
mx_timer_status_t mx_timer_status (mx_timer_pt ptimer);
/* check whether the timer is timeout */
mx_bool_t mx_timer_istimeout (mx_timer_pt ptimer);
/* check whether the timer is enable */
mx_bool_t mx_timer_isenable (mx_timer_pt ptimer);
/* check whether the timer is disable */
mx_bool_t mx_timer_isdisable (mx_timer_pt ptimer);
/* check whether the timer is paused */
mx_bool_t mx_timer_ispause (mx_timer_pt ptimer);
/* get current count of the specified timer */
mx_usize_t mx_timer_getcurrent (mx_timer_pt ptimer);
/* change the mode of specified timer */
void mx_timer_chmode (mx_timer_pt ptimer, mx_timer_mode_t mode);
/* get the global time, the cumulative running milliseconds */
mx_uint64_t mx_timer_globaltime (void);
/* timer driver function */
void mx_timer_tick (void);

#endif
